#!/usr/bin/env python
# coding: utf8

"""
   RPX Authentication for web2py
   Developed by Nathan Freeze (Copyright © 2009)
   Email <nathan@freezable.com>
   Modified by Massimo Di Pierro

   This file contains code to allow using RPXNow.com (now Jainrain.com)
   services with web2py
"""

import json
import os
import re
from urllib.parse import urlencode

from gluon import *
from gluon.storage import Storage
from gluon.tools import fetch


class RPXAccount(object):
    """
    from gluon.contrib.login_methods.rpx_account import RPXAccount
    auth.settings.actions_disabled=['register','change_password',
        'request_reset_password']
    auth.settings.login_form = RPXAccount(request,
              api_key="...",
              domain="...",
              url = "http://localhost:8000/%s/default/user/login" % request.application)
    """

    def __init__(
        self,
        request,
        api_key="",
        domain="",
        url="",
        embed=True,
        auth_url="https://rpxnow.com/api/v2/auth_info",
        language="en",
        prompt="rpx",
        on_login_failure=None,
    ):
        self.request = request
        self.api_key = api_key
        self.embed = embed
        self.auth_url = auth_url
        self.domain = domain
        self.token_url = url
        self.language = language
        self.profile = None
        self.prompt = prompt
        self.on_login_failure = on_login_failure
        self.mappings = Storage()

        dn = {"givenName": "", "familyName": ""}
        self.mappings.Facebook = lambda profile, dn=dn: dict(
            registration_id=profile.get("identifier", ""),
            username=profile.get("preferredUsername", ""),
            email=profile.get("email", ""),
            first_name=profile.get("name", dn).get("givenName", ""),
            last_name=profile.get("name", dn).get("familyName", ""),
        )
        self.mappings.Google = lambda profile, dn=dn: dict(
            registration_id=profile.get("identifier", ""),
            username=profile.get("preferredUsername", ""),
            email=profile.get("email", ""),
            first_name=profile.get("name", dn).get("givenName", ""),
            last_name=profile.get("name", dn).get("familyName", ""),
        )
        self.mappings.default = lambda profile: dict(
            registration_id=profile.get("identifier", ""),
            username=profile.get("preferredUsername", ""),
            email=profile.get("email", ""),
            first_name=profile.get("preferredUsername", ""),
            last_name="",
        )

    def get_user(self):
        request = self.request
        # Janrain now sends the token via both a POST body and the query
        # string, so we should keep only one of these.
        token = request.post_vars.token or request.get_vars.token
        if token:
            user = Storage()
            data = urlencode(dict(apiKey=self.api_key, token=token))
            auth_info_json = fetch(self.auth_url + "?" + data)
            auth_info = json.loads(auth_info_json)

            if auth_info["stat"] == "ok":
                self.profile = auth_info["profile"]
                provider = re.sub("[^\w\-]", "", self.profile["providerName"])
                user = self.mappings.get(provider, self.mappings.default)(self.profile)
                return user
            elif self.on_login_failure:
                redirect(self.on_login_failure)
        return None

    def login_form(self):
        request = self.request
        args = request.args
        if self.embed:
            JANRAIN_URL = (
                "https://%s.rpxnow.com/openid/embed?token_url=%s&language_preference=%s"
            )
            rpxform = IFRAME(
                _src=JANRAIN_URL % (self.domain, self.token_url, self.language),
                _scrolling="no",
                _frameborder="no",
                _style="width:400px;height:240px;",
            )
        else:
            JANRAIN_URL = "https://%s.rpxnow.com/openid/v2/signin?token_url=%s"
            rpxform = DIV(
                SCRIPT(
                    _src="https://rpxnow.com/openid/v2/widget", _type="text/javascript"
                ),
                SCRIPT(
                    "RPXNOW.overlay = true;",
                    "RPXNOW.language_preference = '%s';" % self.language,
                    "RPXNOW.realm = '%s';" % self.domain,
                    "RPXNOW.token_url = '%s';" % self.token_url,
                    "RPXNOW.show();",
                    _type="text/javascript",
                ),
            )
        return rpxform


def use_janrain(auth, filename="private/janrain.key", **kwargs):
    path = os.path.join(current.request.folder, filename)
    if os.path.exists(path):
        request = current.request
        domain, key = open(path, "r").read().strip().split(":")
        host = current.request.env.http_host
        url = URL("default", "user", args="login", scheme=True)
        auth.settings.actions_disabled = [
            "register",
            "change_password",
            "request_reset_password",
        ]
        auth.settings.login_form = RPXAccount(
            request, api_key=key, domain=domain, url=url, **kwargs
        )
